﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Data.SqlClient;
using System.Linq;
using System.Web.Mvc;
using SacNetUG.Models;

namespace SacNetUG.Controllers
{
    public partial class EventController : Controller
    {
        public virtual ActionResult Index(int? id)
        {
            ViewData["RenderAdminLink"] = Models.User.UserInRole(HttpContext.User.Identity.Name, "Admin");
            return View(GetPaginatedEventList(id ?? 1));
        }

        [Authorize]
        public virtual ActionResult Create()
        {
            return View();
        }

        public virtual ActionResult Reminder()
        {
            return View(repository.GetNextEvent());
        }

        public virtual ActionResult Agenda()
        {
            return View(repository.GetNextEvent());
        }

        [Authorize, HttpPost]
        public ContentResult Attended(int userId, bool attending)
        {
            var evt = repository.GetNextEvent();
            if (evt == null) return Content("Unable to load event");

            try
            {
                var db = new SacNetUGDataContext();
                var rsvp = db.RSVPs.FirstOrDefault(p => p.UserId == userId && p.EventId == evt.EventId);

                if (rsvp == null) return Content("Unable to load user");

                rsvp.Attended = attending;

                db.SubmitChanges();
            }
            catch (Exception ex)
            {
                return Content(string.Format("An error occurred: {0}", ex.Message));
            }

            return Content("");
        }

        [Authorize, HttpPost]
        public ContentResult AddUserById(int userId)
        {
            var evt = repository.GetNextEvent();
            if (evt == null) return Content("Unable to load event");

            try
            {
                var db = new SacNetUGDataContext();
                var rsvp = new RSVP {Attended = true, EventId = evt.EventId, UserId = userId, WillAttend = true};
                db.RSVPs.InsertOnSubmit(rsvp);
                db.SubmitChanges();
            }
            catch (Exception ex)
            {
                return Content(string.Format("An error occurred: {0}", ex.Message));
            }

            return Content("");
        }

        [Authorize, HttpPost]
        public ContentResult CreateUser(string name, string last, string email)
        {
            var evt = repository.GetNextEvent();
            if (evt == null) return Content("Unable to load event");

            try
            {
                var db = new SacNetUGDataContext();

                var user = new User {AuthID = "Mailing List", EmailAddress = email, FirstName = name, LastName = last};
                db.Users.InsertOnSubmit(user);
                var rsvp = new RSVP { Attended = true, EventId = evt.EventId, User = user, WillAttend = true };
                db.RSVPs.InsertOnSubmit(rsvp);
                db.SubmitChanges();
            }
            catch (Exception ex)
            {
                return Content(string.Format("An error occurred: {0}", ex.Message));
            }

            return Content("");
        }

        [Authorize, HttpPost]
        public PartialViewResult FindUser(string name, string last, string email)
        {
            //var evt = repository.GetNextEvent();
            //if (evt == null) return Content("Unable to load event");

            try
            {
                var db = new SacNetUGDataContext();
                var users = db.Users.AsQueryable();
                if(name.Length > 0)
                    users = users.Where(
                        p =>
                        p.FirstName.Contains(name));

                if (last.Length > 0)
                    users = users.Where(
                        p => p.LastName.Contains(last));


                if (email.Length > 0)
                    users = users.Where(
                        p => p.EmailAddress.Contains(email));

                return users.Count() > 0 ? PartialView("FoundUsers", users) : PartialView("AjaxError", "No users found");
            }
            catch (Exception ex)
            {
                return PartialView("AjaxError", ex.Message);
            }
        }

        [Authorize]
        [AcceptVerbs(HttpVerbs.Post)]
        [ValidateInput(false)]
        public virtual ActionResult Create(Event ev)
        {
            try
            {
                ev.SanitizeInput();
                ev.EndDate = ev.StartDate;

                ev.StartDate = GetActualDateTime(ev.StartDate, Request.Form, "startTime");
                ev.EndDate = GetActualDateTime(ev.EndDate, Request.Form, "endTime");


                if (!ModelState.IsValid)
                    return View(ev);

                repository.Db.InsertOnSubmit(ev);
                repository.Db.SubmitChanges();

                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

        [Authorize]
        public virtual ActionResult Edit(int id)
        {
            if (id == 0) return View(Views.Create);

            Event thisEvent = repository.GetEvent(id);

            ViewData.Add("presenterList", GetEventPresenterList(thisEvent));
            ViewData.Add("sponsorList", GetEventSponsorList(thisEvent));

            return View(thisEvent);
        }

        [Authorize]
        [AcceptVerbs(HttpVerbs.Post)]
        [ValidateInput(false)]
        public virtual ActionResult Edit(int id, Event ev)
        {
            try
            {
                ev.SanitizeInput();

                if (!ModelState.IsValid)
                    return View(ev);

                UpdateModel(repository.GetEvent(id));
                repository.Db.SubmitChanges();

                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

        public virtual ActionResult Detail(int id)
        {
            Event returnEvent = repository.GetEvent(id);

            return returnEvent == null ? View("NotFound") : View(returnEvent);
        }

        [Authorize]
        [HttpGet]
        public virtual ActionResult Rsvp()
        {
            Event nextEvent = repository.GetNextEvent();

            if (nextEvent == null)
            {
                ViewData["Unavailable"] = "The next event has not yet been determined";
                return View();
            }

            return View(GetRsvpViewModel(nextEvent));
        }

        [Authorize]
        [HttpGet]
        public virtual ActionResult Rsvps()
        {
            var nextEvent = repository.GetNextEvent();

            if (nextEvent == null)
            {
                ViewData["Unavailable"] = "The next event has not yet been determined";
                return View(new List<RSVP>());
            }

            var db = new SacNetUGDataContext();
            ViewData["nextEvent"] = nextEvent;
            return View(db.RSVPs.Where(p => p.EventId == nextEvent.EventId));
        }

        [Authorize]
        [AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult AddPresenter(int id, FormCollection collection)
        {
            int userId = int.Parse(collection["presenterList"]);
            var dc = new SacNetUGDataContext();
            var newPresenter = new EventPresenter {UserId = userId, EventId = id};

            dc.EventPresenters.InsertOnSubmit(newPresenter);
            dc.SubmitChanges();

            Event thisEvent = repository.GetEvent(id);

            ViewData.Add("presenterList", GetEventPresenterList(thisEvent));
            return PartialView("EventPresenterEdit", thisEvent);
        }

        [Authorize]
        public virtual ActionResult RemovePresenter(int eventId, int userId)
        {
            var dc = new SacNetUGDataContext();

            EventPresenter presenter =
                dc.EventPresenters.Where(p => p.EventId == eventId && p.UserId == userId).Single();
            dc.EventPresenters.DeleteOnSubmit(presenter);
            dc.SubmitChanges();

            Event thisEvent = repository.GetEvent(eventId);
            ViewData.Add("presenterList", GetEventPresenterList(thisEvent));
            return PartialView("EventPresenterEdit", thisEvent);
        }

        [Authorize]
        [AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult AddSponsor(int id, FormCollection collection)
        {
            int sponsorId = int.Parse(collection["sponsorList"]);
            var dc = new SacNetUGDataContext();
            var newSponsor = new EventSponsor {SponsorId = sponsorId, EventId = id, Blurb = "", SortOrder = 1};
            dc.EventSponsors.InsertOnSubmit(newSponsor);
            dc.SubmitChanges();

            Event thisEvent = repository.GetEvent(id);

            ViewData.Add("sponsorList", GetEventSponsorList(thisEvent));
            return PartialView("EventSponsorEdit", thisEvent);
        }

        [Authorize]
        public virtual ActionResult RemoveSponsor(int eventId, int sponsorId)
        {
            //int userId = int.Parse(collection["presenterList"].ToString());
            var dc = new SacNetUGDataContext();
            EventSponsor sponsor =
                dc.EventSponsors.Where(s => s.SponsorId == sponsorId && s.EventId == eventId).Single();
            dc.EventSponsors.DeleteOnSubmit(sponsor);
            dc.SubmitChanges();

            Event thisEvent = repository.GetEvent(eventId);
            ViewData.Add("sponsorList", GetEventSponsorList(thisEvent));
            return PartialView("EventSponsorEdit", thisEvent);
        }

        private static PaginatedList<Event> GetPaginatedEventList(int page)
        {
            const int pageSize = 2;
            var db = new SacNetUGDataContext();
            var paginatedList = new PaginatedList<Event>(db.GetTable<Event>().OrderByDescending(e => e.StartDate), page,
                                                         pageSize);
            return paginatedList;
        }

        private static SelectList GetEventPresenterList(Event thisEvent)
        {
            var dc = new SacNetUGDataContext();
           // EntitySet<EventPresenter> eventPresenters = thisEvent.EventPresenters;

            var allPresenters = from ap in dc.Users
                                                    where !(from ep in thisEvent.EventPresenters
                                                            select ep.UserId).Contains(ap.Id)
                                                    orderby ap.FirstName , ap.LastName
                                                    select ap;
            return new SelectList(allPresenters, "Id", "Name");
        }

        private static SelectList GetEventSponsorList(Event thisEvent)
        {
            var dc = new SacNetUGDataContext();
           // EntitySet<EventSponsor> eventSponsors = thisEvent.EventSponsors;
            var allSponsors = from sp in dc.Sponsors
                                              where !(from es in thisEvent.EventSponsors
                                                      select es.SponsorId).Contains(sp.SponsorId)
                                              select sp;
            //select sp;
            return new SelectList(allSponsors, "SponsorId", "Name");
        }


        private RsvpViewModel GetRsvpViewModel(Event nextEvent)
        {
            var viewModel = new RsvpViewModel {Event = nextEvent, EventId = nextEvent.EventId};
            var possibleResponses = new List<SelectListItem>();

            User user = repository.GetUser(HttpContext.User.Identity.Name);
            RSVP rsvp = repository.GetRsvp(user, nextEvent.EventId);

            if (rsvp == null)
            {
                possibleResponses.Add(new SelectListItem {Text = "Yes, I will attend", Value = "Yes"});
                possibleResponses.Add(new SelectListItem {Text = "No, I will not attend", Value = "No"});
            }
            else
            {
                possibleResponses.Add(rsvp.WillAttend
                                          ? new SelectListItem
                                                {Text = "No, I will no longer be attending", Value = "No"}
                                          : new SelectListItem {Text = "Yes, I now plan on attending", Value = "Yes"});
            }

            viewModel.Responses = new SelectList(possibleResponses, "Value", "Text");
            return viewModel;
        }

        [Authorize]
        [HttpPost]
        public virtual ActionResult Rsvp(int eventId, string willAttend)
        {
            //check for duplicates
            User user = repository.GetUser(HttpContext.User.Identity.Name);

            //create new rsvp and save it
            var db = new SacNetUGDataContext();
            RSVP r = db.RSVPs.FirstOrDefault(p => p.EventId == eventId && p.UserId == user.Id);
            if (r == null)
            {
                r = new RSVP {EventId = eventId, UserId = user.Id};
                db.RSVPs.InsertOnSubmit(r);
            }

            r.WillAttend = willAttend == "Yes";

            db.SubmitChanges();

            TempData["RsvpMessage"] = "Thanks for confirming, we'll see you there";
            return RedirectToAction("Index", "Home");
        }

        private static DateTime GetActualDateTime(DateTime wholeDay, NameValueCollection collection, string namePrefix)
        {
            double hour = double.Parse(collection[namePrefix + "Hours"]);
            double minute = double.Parse(collection[namePrefix + "Minutes"]);
            string amPm = collection[namePrefix + "AmPm"];

            DateTime newDate = wholeDay;

            if (!(amPm == "AM" && hour == 12))
            {
                newDate = newDate.AddHours(hour);
                if (amPm == "PM")
                {
                    newDate = newDate.AddHours(12);
                }
                newDate = newDate.AddMinutes(minute);
            }
            return newDate;
        }

        //[Authorize]
        //public virtual ActionResult CreatePresenter()
        //{
        //    return View("CreatePresenter");
        //}
    }
}
